#include <vector>
#include <cassert>
#include <iostream>
#include "connect_board.hpp"

int main()
{
    using namespace clay;

    // Normal cases.
    ConnectBoard<10> connect_board_1;
    for (int i = 0; i < 10; i++) {
        assert(connect_board_1.Map(i) == i);
        assert(connect_board_1.ReverseMap(i) == i);
    }

    // Has plugin cases.
    std::vector<std::pair<std::uint8_t, std::uint8_t>> connect_pair_list = {
        {0, 1},
        {3, 5},
        {4, 2}
    };
    ConnectBoard<10> connect_board_3(connect_pair_list);
    for (auto& pair : connect_pair_list) {
        assert(connect_board_3.Map(pair.first) == pair.second);
        assert(connect_board_3.ReverseMap(pair.first) == pair.second);

        assert(connect_board_3.Map(pair.second) == pair.first);
        assert(connect_board_3.ReverseMap(pair.second) == pair.first);
    }
    for (int i : {6, 7, 8, 9}) {
        assert(connect_board_1.Map(i) == i);
        assert(connect_board_1.ReverseMap(i) == i);
    }

    // Evil cases.
    bool has_exception = false;
    ConnectBoard<10> connect_board_4;
    try {
        connect_board_4.Map(11);
    } catch (const std::exception& e) {
        has_exception = true;
    }
    assert(has_exception);

    // Excessive plugging pairs.
    std::vector<std::pair<std::uint8_t, std::uint8_t>> screw_connect_pair_list = connect_pair_list;
    screw_connect_pair_list.push_back({1, 6});
    screw_connect_pair_list.push_back({3, 7});  // 1, 3 are plugged, thus these two will be ignored.

    ConnectBoard<10> connect_board_5(screw_connect_pair_list);
    for (auto& pair : connect_pair_list) {
        assert(connect_board_5.Map(pair.first) == pair.second);
        assert(connect_board_5.ReverseMap(pair.first) == pair.second);

        assert(connect_board_5.Map(pair.second) == pair.first);
        assert(connect_board_5.ReverseMap(pair.second) == pair.first);
    }
    for (int i : {6, 7, 8, 9}) {
        assert(connect_board_1.Map(i) == i);
        assert(connect_board_1.ReverseMap(i) == i);
    }

    return 0;
}